#include "FreeRTOS.h"
#include "user_task.h"
#include "task.h"
#include "sys.h"

/*========================== Declaration ==========================*/
void task_startTask(void);

/*========================== Macro Define ==========================*/
#define FRAM_TASK_STACK_DEPTH_TYP             u16
#define FRAM_TASK_BASIC_STK_DEP               ((const FRAM_TASK_STACK_DEPTH_TYP) 128)
#define FRAM_TASK_TABLE_CNT                   ((u32)FRAM_TASK_NUM_CNT)
#define FRAM_TASK_BASIC_PRIO                  ((UBaseType_t)4)
#define FRAM_TASK_LED0_PRIO                   (FRAM_TASK_BASIC_PRIO)
#define FRAM_TASK_LED1_PRIO                   (FRAM_TASK_BASIC_PRIO)
#define FRAM_TASK_LED_STK_DEP                 (FRAM_TASK_BASIC_STK_DEP)
#define FRAM_TASK_STARTASK_PRIO               (1)
#define FRAM_TASK_STARTASK_STK_DEP            (FRAM_TASK_BASIC_STK_DEP)
#define FRAM_TASK_LCDSHOW_PRIO                ((UBaseType_t)FRAM_TASK_BASIC_PRIO)
#define FRAM_TASK_LCDSHOW_STK_DEP             (FRAM_TASK_BASIC_STK_DEP)
#define FRAM_TASK_COMM_STK_DEP                (FRAM_TASK_BASIC_STK_DEP)
#define FRAM_TASK_COMM_PRIO                   (2)
#define FRAM_TASK_THMT_STK_DEP                (FRAM_TASK_BASIC_STK_DEP)
#define FRAM_TASK_THMT_PRIO                   (FRAM_TASK_BASIC_PRIO)

/*========================== Struct Define ==========================*/
typedef struct
{
    fram_taskNum_e num,
    TaskFunction_t func;
    const char * const name;
    const FRAM_TASK_STACK_DEPTH_TYP stackDepth;
    void * const param;
    UBaseType_t priority;
    TaskHandle_t * const hdl;
}fram_taskItem_t;

/*========================== Global Var Define ==========================*/
TaskHandle_t task_led0_hdl;
TaskHandle_t task_led1_hdl;
TaskHandle_t task_startTask_hdl;
TaskHandle_t task_lcdShow_hdl;
TaskHandle_t task_comm_hdl;
TaskHandle_t task_thmt_hdl;


fram_taskItem_t task_tbl[FRAM_TASK_TABLE_CNT] =
{
  /*|---------num---------|---------func--------|-------name--------|----stack depth----|---param---|--------priority-------|---handler---|*/
    {
        FRAM_TASK_STARTASK,     task_startTask,    "startTask",        FRAM_TASK_STARTASK_STK_DEP,     NULL,       FRAM_TASK_STARTASK_PRIO,        &task_startTask_hdl
    },
    {
        FRAM_TASK_COMM,         comm_task,         "comm_task",        FRAM_TASK_COMM_STK_DEP,         NULL,       FRAM_TASK_COMM_PRIO,            &task_comm_hdl
    },
    {
        FRAM_TASK_LED0,         task_led0,         "task_led0",        FRAM_TASK_LED_STK_DEP,          NULL,       FRAM_TASK_LED0_PRIO,            &task_led0_hdl
    },
    {
        FRAM_TASK_LED1,         task_led1,         "task_led1",        FRAM_TASK_LED_STK_DEP,          NULL,       FRAM_TASK_LED1_PRIO,            &task_led1_hdl
    },
    {
        FRAM_TASK_LCDSHOW,      task_lcdShow,      "task_lcdShow",     FRAM_TASK_LCDSHOW_STK_DEP,      NULL,       FRAM_TASK_LCDSHOW_PRIO,         &task_lcdShow_hdl
    },
    {
        FRAM_TASK_THMT,         task_tempHumi,     "task_tempHumi",    FRAM_TASK_THMT_STK_DEP,         NULL,       FRAM_TASK_THMT_PRIO,            &task_thmt_hdl
    }
};


/*========================== Function Define ==========================*/
void task_startTask(void)
{
    /*Step1 enter critical region*/
    taskENTER_CRITICAL();

    /*Step2 create task*/
    u32 idx = (u32)FRAM_TASK_STARTASK + 1;
    fram_taskItem_t *item;
    for (;idx < FRAM_TASK_TABLE_CNT;idx++)
    {
        item = &task_tbl[idx];
        xTaskCreate(item->func, item->name, item->stackDepth, item->param, item->priority, item->hdl);
    }

    /*Step3 remove start task*/
    vTaskDelete(task_startTask_hdl);
    LOG_NON("all task created\r\n");

    /*Step4 exit critical region*/
    taskEXIT_CRITICAL();
}

void task_createStart(void)
{
    taskENTER_CRITICAL();

    fram_taskItem_t *item = &task_tbl[FRAM_TASK_STARTASK];
    xTaskCreate(item->func, item->name, item->stackDepth, item->param, item->priority, item->hdl);

    taskEXIT_CRITICAL();
}


